package com.yang.webapi.module.utils.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;



/**
 * Created by baipan
 * Date: 2019/12/19
 * HttpAPI Helper
 * HttpClient4使用InputStream.close()来确认连接关闭
 * 当返回码无论是200还是其他，都应该被关闭
 * InputStream必须被关闭，不然会导致资源一直被占用
 */
@Component
public class HttpAPIService {


    @Autowired
    private HttpClient httpClient;
    @Resource
    RequestConfig.Builder builder;


    /**
     * 使用HTTP发送GET请求
     */
    public String doGet(String url) throws Exception {
        String result = null;
        CloseableHttpResponse response = null;
        HttpEntity httpEntity = null;
        try {
            HttpGet httpGet = new HttpGet(url);
            httpGet.setConfig(httpClient.getRequestConfig(builder));
            response = httpClient.getHttpClient().execute(httpGet);
            httpEntity = response.getEntity();
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                //toString中会自动关闭InputStream
                result = EntityUtils.toString(httpEntity, "UTF-8");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if (httpEntity!=null) {
                    //关闭inputStream
                    EntityUtils.consume(httpEntity);
                }
            }catch (IOException e){
                e.printStackTrace();
            }
            if (response!=null) {
                response.close();
            }
        }
        return result;
    }


    /**
     * 使用HTTP发送POST请求-以body方式发送请求参数
     */
    public HttpResult doPost(String url, Map<String, Object> map, Map<String, String> headerMap) {
        HttpResult httpResult = null;
        CloseableHttpResponse response = null;
        HttpEntity httpEntity = null;
        try {
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(httpClient.getRequestConfig(builder));
            if (map != null) {
                StringEntity s = new StringEntity(JSONObject.toJSONString(map), Charset.forName("UTF-8"));
                s.setContentEncoding("UTF-8");
                s.setContentType("application/json");
                httpPost.setEntity(s);
            }

            if (headerMap != null) {
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    httpPost.setHeader(entry.getKey(), entry.getValue());
                }
            }
            response = httpClient.getHttpClient().execute(httpPost);
            httpEntity = response.getEntity();
            httpResult = new HttpResult(response.getStatusLine().getStatusCode(), EntityUtils.toString(httpEntity, "UTF-8"));
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if (httpEntity!=null) {
                    EntityUtils.consume(httpEntity);
                }
            }catch (IOException e){
                e.printStackTrace();
            }
            if (response!=null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return httpResult;
    }


    /**
     * 使用HTTP发送POST请求-以query方式发送请求参数
     */
    public HttpResult doPostForm(String url, Map<String, String> map, Map<String, String> headerMap) throws Exception {
        HttpResult httpResult = null;
        CloseableHttpResponse response = null;
        HttpEntity httpEntity = null;
        try {
            HttpPost httpPost = new HttpPost(url);
            ArrayList<BasicNameValuePair> pairs = new ArrayList<>();
            for (Map.Entry<String, String> entry : map.entrySet()) {
                pairs.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
            }
            if (headerMap != null) {
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    httpPost.setHeader(entry.getKey(), entry.getValue());
                }
            }
            UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(pairs, Charset.forName("UTF-8"));
            urlEncodedFormEntity.setContentEncoding("UTF-8");
            httpPost.setEntity(urlEncodedFormEntity);
            response = httpClient.getHttpClient().execute(httpPost);
            httpEntity = response.getEntity();
            httpResult = new HttpResult(response.getStatusLine().getStatusCode(), EntityUtils.toString(httpEntity, "UTF-8"));
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if (httpEntity!=null) {
                    EntityUtils.consume(httpEntity);
                }
            }catch (IOException e){
                e.printStackTrace();
            }
            if (response!=null) {
                response.close();
            }
        }
        return httpResult;
    }










    public String doGet(String url, Map<String, Object> map) throws Exception {
        URIBuilder uriBuilder = new URIBuilder(url);
        if (map != null) {
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
            }
        }
        return this.doGet(uriBuilder.build().toString());
    }

    public String doGet(String url, Object object) throws Exception {
        URIBuilder uriBuilder = new URIBuilder(url);
        HashMap<String, Object> hashMap = null;
        if (object != null) {
            hashMap = JSONObject.parseObject(JSON.toJSONString(object), HashMap.class);
        }
        if (hashMap != null) {
            for (Map.Entry<String, Object> entry : hashMap.entrySet()) {
                uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
            }
        }
        return this.doGet(uriBuilder.build().toString());
    }


    public HttpResult doPost(String url, Map<String, Object> map) throws Exception {
        return this.doPost(url, map, null);
    }


    public HttpResult doPost(String url, Object object) throws RuntimeException {
        HashMap<String, Object> hashMap = null;
        if (object != null) {
            hashMap = JSONObject.parseObject(JSON.toJSONString(object), HashMap.class);
        }
        return doPost(url, hashMap, null);
    }
}